#include "paging_controller.h"
#include <napi/native_api.h>
#include <js_native_api.h>
#include <js_native_api_types.h>
#include <functional>
#include <memory>
#include <string>
#include <vector>

// ============ NAPI工具函数 ============

class NAPIUtils {
public:
    static napi_value CreateString(napi_env env, const std::string& str) {
        napi_value result;
        napi_create_string_utf8(env, str.c_str(), str.length(), &result);
        return result;
    }
    
    static std::string GetString(napi_env env, napi_value value) {
        size_t length = 0;
        napi_get_value_string_utf8(env, value, nullptr, 0, &length);
        std::string str(length, '\0');
        napi_get_value_string_utf8(env, value, &str[0], length + 1, &length);
        return str;
    }
    
    static int32_t GetInt32(napi_env env, napi_value value) {
        int32_t result;
        napi_get_value_int32(env, value, &result);
        return result;
    }
    
    static bool GetBool(napi_env env, napi_value value) {
        bool result;
        napi_get_value_bool(env, value, &result);
        return result;
    }
    
    static napi_value CreateInt32(napi_env env, int32_t value) {
        napi_value result;
        napi_create_int32(env, value, &result);
        return result;
    }
    
    static napi_value CreateBool(napi_env env, bool value) {
        napi_value result;
        napi_get_boolean(env, value, &result);
        return result;
    }
};

// ============ List控制器NAPI包装 ============

class PagingListControllerNAPI {
private:
    std::unique_ptr<PagingListViewController<std::string>> controller;
    napi_env env_;
    napi_ref itemBuilderRef_ = nullptr;
    napi_ref onDataChangedRef_ = nullptr;
    napi_ref onDataInsertedRef_ = nullptr;
    napi_ref onDataRemovedRef_ = nullptr;
    
public:
    PagingListControllerNAPI() {
        controller = std::make_unique<PagingListViewController<std::string>>();
    }
    
    ~PagingListControllerNAPI() {
        if (itemBuilderRef_) {
            napi_delete_reference(env_, itemBuilderRef_);
        }
        if (onDataChangedRef_) {
            napi_delete_reference(env_, onDataChangedRef_);
        }
        if (onDataInsertedRef_) {
            napi_delete_reference(env_, onDataInsertedRef_);
        }
        if (onDataRemovedRef_) {
            napi_delete_reference(env_, onDataRemovedRef_);
        }
    }
    
    // 设置Item构建器
    void SetItemBuilder(napi_env env, napi_value callback) {
        env_ = env;
        if (itemBuilderRef_) {
            napi_delete_reference(env, itemBuilderRef_);
        }
        napi_create_reference(env, callback, 1, &itemBuilderRef_);
        
        controller->setItemBuilder([this, env](std::shared_ptr<PagingItem<std::string>> item, int index) {
            napi_value callback;
            napi_get_reference_value(env, itemBuilderRef_, &callback);
            
            napi_value itemObj;
            napi_create_object(env, &itemObj);
            napi_set_named_property(env, itemObj, "id", NAPIUtils::CreateString(env, item->id));
            napi_set_named_property(env, itemObj, "data", NAPIUtils::CreateString(env, item->data));
            
            napi_value args[2];
            args[0] = itemObj;
            args[1] = NAPIUtils::CreateInt32(env, index);
            
            napi_value result;
            napi_call_function(env, nullptr, callback, 2, args, &result);
            
            // 从JS返回值获取节点句柄
            void* nodeHandle = nullptr;
            napi_get_value_external(env, result, &nodeHandle);
            
            return static_cast<ArkUI_NodeHandle>(nodeHandle);
        });
    }
    
    // 提交数据
    void SubmitData(napi_env env, napi_value dataArray) {
        uint32_t length;
        napi_get_array_length(env, dataArray, &length);
        
        std::vector<std::shared_ptr<PagingItem<std::string>>> items;
        for (uint32_t i = 0; i < length; i++) {
            napi_value element;
            napi_get_element(env, dataArray, i, &element);
            
            auto item = std::make_shared<PagingItem<std::string>>();
            
            napi_value idValue;
            napi_get_named_property(env, element, "id", &idValue);
            item->id = NAPIUtils::GetString(env, idValue);
            
            napi_value dataValue;
            napi_get_named_property(env, element, "data", &dataValue);
            item->data = NAPIUtils::GetString(env, dataValue);
            
            items.push_back(item);
        }
        
        PagingData<std::string> pagingData(items);
        controller->submitData(pagingData);
    }
    
    // 刷新
    void Refresh() {
        controller->refresh();
    }
    
    // 获取项数量
    size_t GetItemCount() {
        return controller->getItemCount();
    }
    
    // 获取节点句柄
    ArkUI_NodeHandle GetNode() {
        return controller->getListNode();
    }
    
    // 设置数据变化监听器
void SetDataChangeListeners(napi_env env, 
                            napi_value onChanged,
                            napi_value onInserted, 
                            napi_value onRemoved) {
    env_ = env;
    
    // 使用 std::function 类型来存储回调
    std::function<void(int, int)> changedCallback = nullptr;
    std::function<void(int, int)> insertedCallback = nullptr;
    std::function<void(int, int)> removedCallback = nullptr;
    
    if (onChanged != nullptr) {
        if (onDataChangedRef_) {
            napi_delete_reference(env, onDataChangedRef_);
        }
        napi_create_reference(env, onChanged, 1, &onDataChangedRef_);
        
        changedCallback = [this, env](int pos, int count) {
            napi_value callback;
            napi_get_reference_value(env, onDataChangedRef_, &callback);
            
            napi_value args[2];
            args[0] = NAPIUtils::CreateInt32(env, pos);
            args[1] = NAPIUtils::CreateInt32(env, count);
            
            napi_value result;
            napi_call_function(env, nullptr, callback, 2, args, &result);
        };
    }
    
    if (onInserted != nullptr) {
        if (onDataInsertedRef_) {
            napi_delete_reference(env, onDataInsertedRef_);
        }
        napi_create_reference(env, onInserted, 1, &onDataInsertedRef_);
        
        insertedCallback = [this, env](int pos, int count) {
            napi_value callback;
            napi_get_reference_value(env, onDataInsertedRef_, &callback);
            
            napi_value args[2];
            args[0] = NAPIUtils::CreateInt32(env, pos);
            args[1] = NAPIUtils::CreateInt32(env, count);
            
            napi_value result;
            napi_call_function(env, nullptr, callback, 2, args, &result);
        };
    }
    
    if (onRemoved != nullptr) {
        if (onDataRemovedRef_) {
            napi_delete_reference(env, onDataRemovedRef_);
        }
        napi_create_reference(env, onRemoved, 1, &onDataRemovedRef_);
        
        removedCallback = [this, env](int pos, int count) {
            napi_value callback;
            napi_get_reference_value(env, onDataRemovedRef_, &callback);
            
            napi_value args[2];
            args[0] = NAPIUtils::CreateInt32(env, pos);
            args[1] = NAPIUtils::CreateInt32(env, count);
            
            napi_value result;
            napi_call_function(env, nullptr, callback, 2, args, &result);
        };
    }
    
    controller->setDataChangeListeners(changedCallback, insertedCallback, removedCallback);
}
};

// ============ NAPI导出函数 ============

// 创建List控制器
static napi_value CreatePagingListController(napi_env env, napi_callback_info info) {
    auto* controller = new PagingListControllerNAPI();
    
    napi_value result;
    napi_create_external(env, controller, 
        [](napi_env env, void* data, void* hint) {
            delete static_cast<PagingListControllerNAPI*>(data);
        }, nullptr, &result);
    
    return result;
}

// 提交数据
static napi_value SubmitData(napi_env env, napi_callback_info info) {
    size_t argc = 2;
    napi_value args[2];
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    PagingListControllerNAPI* controller;
    napi_get_value_external(env, args[0], reinterpret_cast<void**>(&controller));
    
    controller->SubmitData(env, args[1]);
    
    napi_value undefined;
    napi_get_undefined(env, &undefined);
    return undefined;
}

// 刷新
static napi_value Refresh(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1];
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    PagingListControllerNAPI* controller;
    napi_get_value_external(env, args[0], reinterpret_cast<void**>(&controller));
    
    controller->Refresh();
    
    napi_value undefined;
    napi_get_undefined(env, &undefined);
    return undefined;
}

// 获取项数量
static napi_value GetItemCount(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1];
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    PagingListControllerNAPI* controller;
    napi_get_value_external(env, args[0], reinterpret_cast<void**>(&controller));
    
    return NAPIUtils::CreateInt32(env, controller->GetItemCount());
}

// 获取节点
static napi_value GetNode(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1];
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    PagingListControllerNAPI* controller;
    napi_get_value_external(env, args[0], reinterpret_cast<void**>(&controller));
    
    napi_value result;
    napi_create_external(env, controller->GetNode(), nullptr, nullptr, &result);
    return result;
}

// 设置Item构建器
static napi_value SetItemBuilder(napi_env env, napi_callback_info info) {
    size_t argc = 2;
    napi_value args[2];
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    PagingListControllerNAPI* controller;
    napi_get_value_external(env, args[0], reinterpret_cast<void**>(&controller));
    
    controller->SetItemBuilder(env, args[1]);
    
    napi_value undefined;
    napi_get_undefined(env, &undefined);
    return undefined;
}

// 设置数据变化监听器
static napi_value SetDataChangeListeners(napi_env env, napi_callback_info info) {
    size_t argc = 4;
    napi_value args[4];
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    PagingListControllerNAPI* controller;
    napi_get_value_external(env, args[0], reinterpret_cast<void**>(&controller));
    
    controller->SetDataChangeListeners(env, 
        argc > 1 ? args[1] : nullptr,
        argc > 2 ? args[2] : nullptr, 
        argc > 3 ? args[3] : nullptr);
    
    napi_value undefined;
    napi_get_undefined(env, &undefined);
    return undefined;
}

// ============ 模块初始化 ============

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        {"createPagingListController", nullptr, CreatePagingListController, 
         nullptr, nullptr, nullptr, napi_default, nullptr},
        {"submitData", nullptr, SubmitData, 
         nullptr, nullptr, nullptr, napi_default, nullptr},
        {"refresh", nullptr, Refresh, 
         nullptr, nullptr, nullptr, napi_default, nullptr},
        {"getItemCount", nullptr, GetItemCount, 
         nullptr, nullptr, nullptr, napi_default, nullptr},
        {"getNode", nullptr, GetNode, 
         nullptr, nullptr, nullptr, napi_default, nullptr},
        {"setItemBuilder", nullptr, SetItemBuilder, 
         nullptr, nullptr, nullptr, napi_default, nullptr},
        {"setDataChangeListeners", nullptr, SetDataChangeListeners, 
         nullptr, nullptr, nullptr, napi_default, nullptr},
    };
    
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "entry",  // 修正：改为 "entry" 与 CMakeLists.txt 一致
    .nm_priv = ((void*)0),
    .reserved = { 0 },
};

extern "C" __attribute__((constructor)) void RegisterPagingControllerModule(void) {
    napi_module_register(&demoModule);
}